package testcase;

import static org.junit.Assert.*;
import org.junit.Test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

import view.FileIO;
import information.Line;


/**
 * @author Rigsby Chi(52584035), Sam Cheung(52603693), Michael Lau(52611921)
 * @version for FileIO.java v3.0.1
 * @since 30-03-2013
 */

public class FileIOTest {
	private final String ENTER = System.lineSeparator();

	// TESTS for readNumOfPierFromTxt()
	@Test
	// Test case 1: Valid Data
	public void tesetReadNumOfPierFromTxt_normal() {
		File f = new File("out.txt");
		try {
			FileOutputStream FOS = new FileOutputStream(f);
			FOS.write("3".getBytes());
			FOS.close();
			FOS.flush();
			FOS = null;
			System.gc();
		} catch (IOException e) {
			e.printStackTrace();
		}
		FileIO fileIO = new FileIO();
		int result = fileIO.readNumOfPierFromTxt();
		fileIO.closeScanner();
		f.delete();
		assertEquals(result, 3);
	}

	@Test
	// Test case 2: No previous data
	public void testReadNumOfPierFromTxt_fileNotFound() {
		System.gc();
		File f = new File("out.txt");
		f.delete();
		FileIO fileIO = new FileIO();
		int result;
		result = fileIO.readNumOfPierFromTxt();
		assertEquals(result, -1);
	}

	@Test
	// Test case 3: Valid Data
	public void testReadInfoOfPiersFromTxt_normal() throws Throwable {
		File f = new File("out.txt");
		try {
			FileOutputStream FOS = new FileOutputStream(f);
			FOS.write("2 2".getBytes());
			FOS.close();
			FOS.flush();
			FOS = null;
			System.gc();
		} catch (IOException e) {
			e.printStackTrace();
		}
		FileIO fileIO = new FileIO();
		int result[];
		result = fileIO.readInfoOfPiersFromTxt(2);
		fileIO.closeScanner();
		f.delete();
		int expectedResult[] = { 2, 2 };
		assertArrayEquals(result, expectedResult);
	}

	// TESTS for readDataFromTxt_CorrectData(Scheduler, int)
	@Test
	// Test case 1: Valid Data
	public void testReadLinesFromTxt_normal() {
		Line[] expected = new Line[3];
		expected[0] = new Line(1000, 30, 1, 15, 1);
		expected[1] = new Line(1100, 30, 1, 15, 1);
		expected[2] = new Line(1200, 60, 1, 15, 1);

		File f = new File("out.txt");
		try {
			FileOutputStream FOS = new FileOutputStream(f);
			String writeData = "1000 30 1 15 1 " + ENTER + "1100 30 1 15 1 "
					+ ENTER + "1200 60 1 15 1";
			FOS.write(writeData.getBytes());
			FOS.close();
			FOS.flush();
			FOS = null;
			System.gc();
		} catch (IOException e) {
			e.printStackTrace();
		}
		FileIO fileIO = new FileIO();
		Line[] result = fileIO.readLinesFromTxt(3);
		fileIO.closeScanner();
		f.delete();

		for (int i = 0; i < 3; i++)
			assertTrue(result[i].equals(expected[i]));
	}

	@Test
	// Test case 2: Invalid Data
	public void testReadDataFromTxt_invalid() {
		Line[] expected = new Line[3];
		expected[0] = new Line(1000, 30, 1, 15, 1);
		expected[1] = new Line(1100, 30, 1, 15, 1);
		expected[2] = new Line(1200, 60, 1, 15, 1);

		File f = new File("out.txt");
		try {
			FileOutputStream FOS = new FileOutputStream(f);
			String writeData = "1000 30 1 15 1 " + ENTER + "1100 30 1 15 1 "
					+ ENTER + "1200 60 1 15 ";
			FOS.write(writeData.getBytes());
			FOS.close();
			FOS.flush();
			FOS = null;
			System.gc();
		} catch (IOException e) {
			e.printStackTrace();
		}
		FileIO fileIO = new FileIO();
		Line[] result = fileIO.readLinesFromTxt(3);
		fileIO.closeScanner();
		f.delete();

		assertArrayEquals(null, result);
	}

	// TESTS for writeDataToTxt(Scheduler, int)
	@Test
	// Test case 1: Valid Data
	public void testWriteDataToTxt_normal() {
		int[] sizeOfPier = { 1, 2, 3 };
		int[] numOfLines = { 2, 1, 1 };
		int[][] line = { { 800, 60, 1, 30, 1 }, { 1000, 60, 1, 30, 1 },
				{ 800, 60, 2, 30, 2 }, { 800, 60, 3, 30, 3 } };

		FileIO fileIO = new FileIO();
		boolean result = fileIO.writeDataToTxt(3, sizeOfPier, numOfLines, line,
				4);

		String getBackData = "";
		File f = new File("out.txt");

		try {
			Scanner s = new Scanner(f);
			while (s.hasNextLine()) {
				getBackData += s.nextLine();
				getBackData += " ";
			}
			s.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.gc();
		// f.delete();
		assertTrue(result);
		assertEquals(
				"3 1 2 3  2 1 1  800 60 1 30 1  1000 60 1 30 1  800 60 2 30 2  800 60 3 30 3  ",
				getBackData);
	}

	@Test
	// Test case 2: Can't write to the text
	public void testWriteDataToTxt_cantWrtieToText() throws IOException {
		File f = new File("out.txt");
		f.createNewFile();
		f.setWritable(false);
		int[] sizeOfPier = { 1, 2, 3 };
		int[] numOfLines = { 2, 1, 1 };
		int[][] line = { { 800, 60, 1, 30, 1 }, { 1000, 60, 1, 30, 1 },
				{ 800, 60, 2, 30, 2 }, { 800, 60, 3, 30, 3 } };

		FileIO fileIO = new FileIO();
		boolean result = fileIO.writeDataToTxt(3, sizeOfPier, numOfLines, line,
				4);
		f.delete();
		assertFalse(result);
	}

	@Test
	// Test case 3: Data are damaged (invalid pier info)
	public void testWriteDataToTxt_damaged_pier() {
		File f = new File("out.txt");
		int[] sizeOfPier = null;
		int[] numOfLines = null;
		int[][] line = { { 800, 60, 1, 30, 1 }, { 1000, 60, 1, 30, 1 },
				{ 800, 60, 2, 30, 2 }, { 800, 60, 3, 30, 3 } };

		FileIO fileIO = new FileIO();
		boolean result = fileIO.writeDataToTxt(3, sizeOfPier, numOfLines, line,
				4);
		f.delete();
		assertFalse(result);
	}

	@Test
	// Test case 4: Data are damaged (invalid line info)
	public void testWriteDataToTxt_damaged_line() {
		File f = new File("out.txt");
		int[] sizeOfPier = { 1, 2, 3 };
		int[] numOfLines = { 2, 1, 1 };
		int[][] line = null;

		FileIO fileIO = new FileIO();
		boolean result = fileIO.writeDataToTxt(3, sizeOfPier, numOfLines, line,
				4);
		f.delete();
		assertFalse(result);
	}

	// TEST for readDataFromTxt(Scheduler, int)
	// and writeDataToTxt(Scheduler, int)
	@Test
	public void testReadAndWrite() {
		int[] sizeOfPier = { 1, 2, 3 };
		int[] numOfLines = { 2, 1, 1 };
		int[][] line = { { 800, 60, 1, 30, 1 }, { 1000, 60, 1, 30, 1 },
				{ 800, 60, 2, 30, 2 }, { 800, 60, 3, 30, 3 } };

		FileIO fileIO = new FileIO();
		fileIO.writeDataToTxt(3, sizeOfPier, numOfLines, line, 4);

		assertEquals(3, fileIO.readNumOfPierFromTxt());
		assertArrayEquals(sizeOfPier, fileIO.readInfoOfPiersFromTxt(3));
		assertArrayEquals(numOfLines, fileIO.readInfoOfPiersFromTxt(3));
		Line[] resultOfLine = fileIO.readLinesFromTxt(4);
		for (int i = 0; i < 4; i++) {
			assertEquals(line[i][0], resultOfLine[i].getStartTime());
			assertEquals(line[i][1], resultOfLine[i].getFreq());
			assertEquals(line[i][2], resultOfLine[i].getRuns());
			assertEquals(line[i][3], resultOfLine[i].getDuration());
			assertEquals(line[i][4], resultOfLine[i].getSizeOfShip());
		}

		File f = new File("out.txt");
		f.delete();
	}
}
